分类
联系方式
  1. 新浪微博
  2. E-mail

Flutter AndroidShellHolder

介绍

AndroidShellHolder 是 Flutter 在 Android 端的核心资源管理类,Flutter 的 4 条线程,就是在该类中创建的。Flutter 中的核心组件 Shell 也是在该类中创建的。由此可见,AndroidShellHolder 是一个非常重要的初始化入口。

构造

AndroidShellHolder 的构造方法是重中之重。这里把该方法拆解来看。

线程创建

首先会创建 Flutter 所需要的线程:

static size_t thread_host_count = 1;
auto thread_label = std::to_string(thread_host_count++);

thread_host_ = std::make_shared<ThreadHost>();

if (is_background_view) {
    *thread_host_ = {thread_label, ThreadHost::Type::UI};
} else {
    *thread_host_ = {thread_label, ThreadHost::Type::UI |
                                   ThreadHost::Type::RASTER |
                                   ThreadHost::Type::IO};
}

其中:

  • 有两种工作模式,通过 is_background_view 辩别
  • 创建 4 条线程

具体线程创建位于 ThreadHost:

ThreadHost::ThreadHost(std::string name_prefix_arg, uint64_t mask)
    : name_prefix(name_prefix_arg) {
  if (mask & ThreadHost::Type::Platform) {
    platform_thread = std::make_unique<fml::Thread>(name_prefix + ".platform");
  }

  if (mask & ThreadHost::Type::UI) {
    ui_thread = std::make_unique<fml::Thread>(name_prefix + ".ui");
  }

  if (mask & ThreadHost::Type::RASTER) {
    raster_thread = std::make_unique<fml::Thread>(name_prefix + ".raster");
  }

  if (mask & ThreadHost::Type::IO) {
    io_thread = std::make_unique<fml::Thread>(name_prefix + ".io");
  }

  if (mask & ThreadHost::Type::Profiler) {
    profiler_thread = std::make_unique<fml::Thread>(name_prefix + ".profiler");
  }
}

需要注意的是,在上面创建的新线程里面,不包含 platform 线程。

还有一点需要注意的是,所创建的线程是 fml::Thread,其内部同时也在线程上生成了消息队列(TaskRunner)

TaskRunner 初始化

接下来需要对各个线程的 TaskRunner 进行初始化:

// 使用当前线程(主线程)作为 Platform Thread
// 因此首先要在主线程上初始化消息队列
fml::MessageLoop::EnsureInitializedForCurrentThread();

// 其它三个 Runner,待会儿从新创建的线程中拿
fml::RefPtr<fml::TaskRunner> raster_runner;
fml::RefPtr<fml::TaskRunner> ui_runner;
fml::RefPtr<fml::TaskRunner> io_runner;

// Platform Runner 直接从当前线程(主线程)拿
fml::RefPtr<fml::TaskRunner> platform_runner =
    fml::MessageLoop::GetCurrent().GetTaskRunner();
    
// 其它三个 Runner,从新创建的线程中拿
if (is_background_view) {
    auto single_task_runner = thread_host_->ui_thread->GetTaskRunner();
    raster_runner = single_task_runner;
    ui_runner = single_task_runner;
    io_runner = single_task_runner;
} else {
    // 通常是这一种
    raster_runner = thread_host_->raster_thread->GetTaskRunner();
    ui_runner = thread_host_->ui_thread->GetTaskRunner();
    io_runner = thread_host_->io_thread->GetTaskRunner();
}

// 把几个 runner 都塞进 TaskRunners 保管
flutter::TaskRunners task_runners(thread_label, // label
                                platform_runner, // platform
                                raster_runner, // raster
                                ui_runner, // ui
                                io_runner // io
);

// raster 线程队列的第一个任务是调整该线程优先级
// 通过 PostTask 向 TaskRunner 抛任务
// 线程优先级,-8 表示最重要的显示线程,raster 优先级略低于显示
// 数字越小优先级越高
task_runners.GetRasterTaskRunner()->PostTask([]() {
    if (::setpriority(PRIO_PROCESS, gettid(), -5) != 0) {
        // 有的系统不让设置优先级太高,再调低点
        if (::setpriority(PRIO_PROCESS, gettid(), -2) != 0) {
            FML_LOG(ERROR) << "Failed to set raster task runner priority";
        }
    }
});

// UI Thread 优先级是 -1
task_runners.GetUITaskRunner()->PostTask([]() {
    if (::setpriority(PRIO_PROCESS, gettid(), -1) != 0) {
        FML_LOG(ERROR) << "Failed to set UI task runner priority";
    }
});
// IO Thread 优先级是 +1
task_runners.GetIOTaskRunner()->PostTask([]() {
    if (::setpriority(PRIO_PROCESS, gettid(), 1) != 0) {
        FML_LOG(ERROR) << "Failed to set IO task runner priority";
    }
});

其中:

  • 可以看到,Platform Thread 直接使用了当前线程(主线程)
  • 因此需要在主线程初始化线程队列 fml::MessageLoop::EnsureInitializedForCurrentThread();
  • 这里的 task_runners 属性待会儿会传给 Shell 中存起来

Shell 创建

Shell 是 Flutter Engine 中非常核心的一个枢纽,通过它能够调度 Flutter Engine 中各个核心组件。

线程准备完毕后,接下来就该 Shell 创建:

shell_ =
    Shell::Create(GetDefaultPlatformData(), // window data
                task_runners, // task runners
                settings_, // settings
                on_create_platform_view, // platform view create callback
                on_create_rasterizer // rasterizer create callback
    );

if (shell_) {
    shell_->GetDartVM()->GetConcurrentMessageLoop()->PostTaskToAllWorkers([]() {
        // DartVM 里面有一个线程池,将优先级调整成 +1
        if (::setpriority(PRIO_PROCESS, gettid(), 1) != 0) {
        FML_LOG(ERROR) << "Failed to set Workers task runner priority";
        }
    });
    
    // 初始化图片解码器
    shell_->RegisterImageDecoder(
        [runner = task_runners.GetIOTaskRunner()](sk_sp<SkData> buffer) {
            return AndroidImageGenerator::MakeFromData(buffer, runner);
        },
        -1);
}

其中:

  • 在 Shell 的创建过程中,还有两个异步惠回调:on_create_platform_view、on_create_rasterizer,也都是非常核心的两个初始化过程,由 Shell 进行调度

下面分别给出两个回调的实现。

on_create_platform_view

fml::WeakPtr<PlatformViewAndroid> weak_platform_view;
Shell::CreateCallback<PlatformView> on_create_platform_view =
    [is_background_view, &jni_facade, &weak_platform_view](Shell& shell) {
        std::unique_ptr<PlatformViewAndroid> platform_view_android;
        platform_view_android = std::make_unique<PlatformViewAndroid>(
            shell, // delegate
            shell.GetTaskRunners(), // task runners
            jni_facade, // JNI interop
            shell.GetSettings()
                .enable_software_rendering, // use software rendering
            !is_background_view // create onscreen surface
        );
        weak_platform_view = platform_view_android->GetWeakPtr();
        auto display = Display(jni_facade->GetDisplayRefreshRate());
        shell.OnDisplayUpdates(DisplayUpdateType::kStartup, {display});
        return platform_view_android;
    };

可以看到创建了一个 PlatformViewAndroid 对象实例。

on_create_rasterizer

Shell::CreateCallback<Rasterizer> on_create_rasterizer = [](Shell& shell) {
    return std::make_unique<Rasterizer>(shell);
};

收尾

在构造方法的最后,AndroidShellHolder 把 PlatformViewAndroid 给存下来了:

  platform_view_ = weak_platform_view;
  FML_DCHECK(platform_view_);
  is_valid_ = shell_ != nullptr;
}

调用

AndroidShellHolder 是在哪里进行创建的呢?

  • attachJNI(platform_view_android_jni_impl.cc),attachJNI 就是 FlutterJNI 的 nativeAttach
    • FlutterJNI.performNativeAttach
      • FlutterJNI.attachToNative
        • FlutterEngine.attachToJni
          • FlutterEngine java 类构造函数